﻿using Amazon.S3;
using Amazon.S3.Model;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Extensions.MediaRss;
using Google.GData.YouTube;
using Google.YouTube;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;


namespace iLikeUSC
{


    public partial class _Default : System.Web.UI.Page
    {
        //public string connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename='|DataDirectory|Database1.mdf';Integrated Security=True;User Instance=True";
        //public string connectionString = @"Server=f907fb24-b006-43ff-9815-a08c001ed8bc.sqlserver.sequelizer.com;Database=dbf907fb24b00643ff9815a08c001ed8bc;User ID=ntsbuwqajwqznotr;Password=uhrYM8CM4Y5ESAYXrdqfPvoEFmtEQPRLY6csqNZErfi66hr5eYKCrN883UsAM65n";
        public string connectionString = ConfigurationManager.ConnectionStrings["iLikeUSCdb"].ConnectionString;

        public DateTime today = DateTime.Now;
        public DateTime votingOpens = new DateTime(2012, 8, 27, 9, 0, 0);
        public DateTime votingCloses = new DateTime(2012, 9, 2, 23, 59, 59);
        public DateTime entriesClose = new DateTime(2012, 8, 24, 23, 59, 59);
        public DateTime entriesOpen = new DateTime(2012, 7, 20, 9, 0, 0);

        public DateTime wk1End = new DateTime(2012, 07, 29, 23, 59, 59);
        public DateTime wk2End = new DateTime(2012, 08, 05, 23, 59, 59);
        public DateTime wk3End = new DateTime(2012, 08, 12, 23, 59, 59);
        public DateTime wk4End = new DateTime(2012, 08, 19, 23, 59, 59);
        public DateTime wk5End = new DateTime(2012, 08, 24, 23, 59, 59);

        public void Page_Load(object sender, EventArgs e)
        {
            this.ClientScript.GetPostBackEventReference(this, string.Empty);

            if (!String.IsNullOrEmpty(Request["__EVENTARGUMENT"]) && Request.Params.Get("__EVENTTARGET") != "makeFinalist" && Request.Params.Get("__EVENTTARGET") != "deleteEntry")
                vote(Request["__EVENTARGUMENT"]);

            GetEntries();
            GetFinalists();

        }

        /// <summary>
        /// Render all entries, separated by week of submission
        /// </summary>
        private void GetEntries()
        {

            DataSet ds = new DataSet();
            SqlDataAdapter daEntries = new SqlDataAdapter();

            try
            {
                using (SqlConnection sql = new SqlConnection(connectionString))
                {
                    sql.Open();
                    
                    daEntries.SelectCommand = new SqlCommand("SELECT TOP 500 * FROM Entries ORDER BY EntryId DESC", sql);                    
                    daEntries.Fill(ds);

                    if (ds.Tables[0].Rows.Count != 0)
                    {
                                              
                        var dv = ds.Tables[0].DefaultView;

                        dv.RowFilter = "Date <= '" + wk1End + "'";
                        var newDt = dv.ToTable();
                        var newDs = new DataSet();  
                        newDs.Tables.Add(newDt);
                                               
                        entryRepeater.DataSource = newDs;
                        entryRepeater.DataBind();


                        dv.RowFilter = "Date >= '" + wk1End + "' AND Date <= '" + wk2End + "'";
                        newDt = dv.ToTable();
                        newDs = new DataSet();
                        newDs.Tables.Add(newDt);
                        if (newDs.Tables[0].Rows.Count != 0)
                        {
                            entryRepeaterWk2.DataSource = newDs;
                            entryRepeaterWk2.DataBind();
                        }

                        dv.RowFilter = "Date >= '" + wk2End + "' AND Date <= '" + wk3End + "'";
                        newDt = dv.ToTable();
                        newDs = new DataSet();
                        newDs.Tables.Add(newDt);
                        if (newDs.Tables[0].Rows.Count != 0)
                        {
                            entryRepeaterWk3.DataSource = newDs;
                            entryRepeaterWk3.DataBind();
                        }

                        dv.RowFilter = "Date >= '" + wk3End + "' AND Date <= '" + wk4End + "'";
                        newDt = dv.ToTable();
                        newDs = new DataSet();
                        newDs.Tables.Add(newDt);
                        if (newDs.Tables[0].Rows.Count != 0)
                        {
                            entryRepeaterWk4.DataSource = newDs;
                            entryRepeaterWk4.DataBind();
                        }

                        dv.RowFilter = "Date >= '" + wk4End + "' AND Date <= '" + wk5End + "'";
                        newDt = dv.ToTable();
                        newDs = new DataSet();
                        newDs.Tables.Add(newDt);
                        if (newDs.Tables[0].Rows.Count != 0)
                        {
                            entryRepeaterWk5.DataSource = newDs;
                            entryRepeaterWk5.DataBind();
                        }
                    }                   
                }
            }
            catch (System.Exception ex) { }
        }

        /// <summary>
        /// Render finalists - finalists have voting option
        /// </summary>
        private void GetFinalists()
        {
            try
            {
                using (SqlConnection sql = new SqlConnection(connectionString))
                {
                    sql.Open();
                    SqlDataAdapter daFinalists = new SqlDataAdapter("SELECT TOP 5 * FROM Entries WHERE Finalist='true'", sql);

                    DataSet ds = new DataSet();
                    daFinalists.Fill(ds);

                    if (ds.Tables[0].Rows.Count != 0)
                    {
                        finalistsRepeater.DataSource = ds;
                        finalistsRepeater.DataBind();
                    }
                }
            }
            catch (System.Exception ex) { }
        }

        /// <summary>
        /// Add vote against entry - catches attempts to vote for same entry multiple times, based on Facebook user ID
        /// </summary>
        /// <param name="id"></param>
        private void vote(string id)
        {
            string voterId = inpHide.Value;
            string entryId = id;

            try
            {
                using (SqlConnection sql = new SqlConnection(connectionString))
                {
                    sql.Open();
                    SqlCommand check = new SqlCommand("SELECT COUNT(*) FROM Votes WHERE EntryID = @entryIdValue AND VoterID = @voterIdValue", sql);
                    check.Parameters.AddWithValue("@entryIdValue", entryId);
                    check.Parameters.AddWithValue("@voterIdValue", voterId);

                    var result = check.ExecuteScalar();

                    if (result.ToString() == "0")
                    {

                        SqlCommand addToVotesTable = new SqlCommand("INSERT INTO Votes (EntryID, VoterID) VALUES (@entryIdValue, @voterIdValue)", sql);
                        addToVotesTable.Parameters.AddWithValue("@entryIdValue", entryId);
                        addToVotesTable.Parameters.AddWithValue("@voterIdValue", voterId);
                        addToVotesTable.ExecuteNonQuery();

                        SqlCommand addToVoteCount = new SqlCommand("UPDATE Entries SET Votes=Votes+1 WHERE EntryId = @entryIdValue", sql);
                        addToVoteCount.Parameters.AddWithValue("@entryIdValue", entryId);
                        addToVoteCount.ExecuteNonQuery();

                        GetEntries();
                        GetFinalists();
                        Response.Redirect("/");
                    }
                    else
                    {
                        finalistText.InnerHtml = "You've already voted for this entry - you can vote multiple times, but only once for each finalist.";
                    }
                }
            }
            catch (Exception ex)
            {
                status.InnerHtml = "Something went wrong. Email <a href='mailto:web@usc.edu.au'>web@usc.edu.au</a>, we'll do our best to help.";
            }
        }
        /*/// <summary>
        /// Set the selected entry as a finalist
        /// </summary>
        /// <param name="id"></param>
        private void setFinalist(string id)
        {
            try
            {
                using (SqlConnection sql = new SqlConnection(connectionString))
                {
                    sql.Open();

                    SqlCommand addToVoteCount = new SqlCommand("UPDATE Entries SET Finalist=Finalist ^ 1 WHERE EntryId = @entryIdValue", sql);
                    addToVoteCount.Parameters.AddWithValue("@entryIdValue", id);
                    addToVoteCount.ExecuteNonQuery();

                    GetEntries();
                    GetFinalists();
                    Response.Redirect("/");
                }
            }
            catch (Exception ex)
            {
                status.InnerHtml = "Something went wrong...";
            }
        }

        /// <summary>
        /// Delete the selected entry
        /// </summary>
        /// <param name="id"></param>
        private void deleteEntry(string id)
        {
            try
            {
                using (SqlConnection sql = new SqlConnection(connectionString))
                {
                    sql.Open();

                    SqlCommand delete = new SqlCommand("DELETE FROM Entries WHERE EntryId = @entryIdValue", sql);
                    delete.Parameters.AddWithValue("@entryIdValue", id);
                    delete.ExecuteNonQuery();

                    delete = new SqlCommand("DELETE FROM Votes WHERE EntryId = @entryIdValue", sql);
                    delete.Parameters.AddWithValue("@entryIdValue", id);
                    delete.ExecuteNonQuery();

                    GetEntries();
                    GetFinalists();
                    Response.Redirect("/");
                }
            }
            catch (Exception ex)
            {
                status.InnerHtml = "Something went wrong";
            }
        }*/

        /// <summary>
        /// Resize uploaded image down to maximum width or height of 600px
        /// </summary>
        /// <param name="src">the image</param>
        /// <param name="maxWidth">600px maximum width</param>
        /// <param name="maxHeight">600px maximum height</param>
        /// <returns>Resized bitmap</returns>
        public Bitmap ResizeImage(Bitmap src, int maxWidth, int maxHeight)
        {
            // original dimensions
            int w = src.Width;
            int h = src.Height;

            // Longest and shortest dimension
            int longestDimension = (w > h) ? w : h;
            int shortestDimension = (w < h) ? w : h;

            // propotionality
            float factor = ((float)longestDimension) / shortestDimension;

            // default width is greater than height
            double newWidth = maxWidth;
            double newHeight = maxWidth / factor;

            // if height greater than width recalculate
            if (w < h)
            {
                newWidth = maxHeight / factor;
                newHeight = maxHeight;
            }

            // Create new Bitmap at new dimensions
            Bitmap result = new Bitmap((int)newWidth, (int)newHeight);
            using (Graphics g = Graphics.FromImage((System.Drawing.Image)result))
                g.DrawImage(src, 0, 0, (int)newWidth, (int)newHeight);
            return result;
        }

        public string UploadVideo(string videoLocation, string fileType, string c, string entrantName)
        {
            string devKey = "AI39si7Sk7Ne_u1EwvgoBpbquOvI78IDCIdewCWszyHp56j1GxePVw0dDFIa_ERb_umHiLRRY1qvH2LHKHW7xj3QW0HVCBvkCw";
            YouTubeRequestSettings settings = new YouTubeRequestSettings("Why iLike USC", devKey, "web@usc.edu.au", "uscwebunit");
            YouTubeRequest request = new YouTubeRequest(settings);            
            
            Video newVideo = new Video();

            newVideo.Title = "Why iLike USC - submission by " + entrantName;
            newVideo.Tags.Add(new MediaCategory("Education", YouTubeNameTable.CategorySchema));
            newVideo.Keywords = "USC, Sunshine Coast, Bestofbothworlds";
            newVideo.Description = c;
            newVideo.YouTubeEntry.Private = true;

            newVideo.YouTubeEntry.MediaSource = new MediaFileSource(videoLocation, fileType);
            Video createdVideo = request.Upload(newVideo);
            string id = createdVideo.Id;

            Match match = Regex.Match(id, @"video:(.*)$");
            id = match.Groups[1].Value;

            return id;
        }

        /// <summary>
        /// Submit entry form - must include either a file or text string, plus name and email.
        /// </summary>
        /// <param name="o"></param>
        /// <param name="e"></param>
        public void uploadBtn_Click(object o, EventArgs e)
        {
            status.InnerHtml = "";

            // make sure there are appropriate form values - should be done as form validation
            if (filename.PostedFile.FileName == "" && textEntry.Value == "")
            {
                status.InnerHtml = "Please select a file or submit a text-only entry.";
                return;
            }
            else if (entrantName.Value == "")
            {
                status.InnerHtml = "Please enter your name.";
                return;
            }
            else if (emailAddress.Value == "")
            {
                status.InnerHtml = "Please enter your email address.";
                return;
            }

            // try save the file to the web server
            if (filename.PostedFile.FileName != "" || textEntry.Value != "")
            {                              
                try
                {
                    using (SqlConnection sql = new SqlConnection(connectionString))
                    {

                        sql.Open();

                        SqlCommand add = new SqlCommand("INSERT INTO Entries (Name, Filename, Caption, Email, Finalist, Type, Date) VALUES (@entrantValue, @fileValue, @captionValue, @emailValue, @finalistValue, @typeValue, @dateValue)", sql);
                        add.Parameters.AddWithValue("@entrantValue", entrantName.Value.Replace("'","''"));
                        add.Parameters.AddWithValue("@captionValue", textEntry.Value.Replace("'","''"));
                        add.Parameters.AddWithValue("@emailValue", emailAddress.Value);
                        add.Parameters.AddWithValue("@finalistValue", "false");
                        add.Parameters.AddWithValue("@dateValue", DateTime.Now);
                        if (filename.PostedFile.FileName != "")
                        {
                            string awsAccessKey = "AKIAJADYGDV2FCMFI6QQ";
                            string awsSecretKey = "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";
                            AmazonS3 client;

                            if (filename.PostedFile.ContentType.Contains("image"))
                            {
                                using (MemoryStream stream = new MemoryStream())
                                {
                                    Bitmap src = Bitmap.FromStream(filename.PostedFile.InputStream) as Bitmap;
                                    // resize image to 600 max width or height
                                    Bitmap result = ResizeImage(src, 600, 600);
                                    result.Save(stream, ImageFormat.Jpeg);

                                    using (client = Amazon.AWSClientFactory.CreateAmazonS3Client(awsAccessKey, awsSecretKey))
                                    {
                                        PutObjectRequest req = new PutObjectRequest();
                                        req.WithBucketName("ilikeusc-resources")
                                            .WithCannedACL(S3CannedACL.PublicRead)
                                            .WithKey("images/" + filename.PostedFile.FileName).InputStream = (System.IO.Stream)stream;
                                        S3Response response = client.PutObject(req);
                                    }

                                    add.Parameters.AddWithValue("@fileValue", filename.PostedFile.FileName);
                                    add.Parameters.AddWithValue("@typeValue", "image");
                                }
                            }
                            else if (filename.PostedFile.ContentType.Contains("video"))
                            {
                                using (client = Amazon.AWSClientFactory.CreateAmazonS3Client(awsAccessKey, awsSecretKey))
                                {
                                    PutObjectRequest req = new PutObjectRequest();
                                    req.WithBucketName("ilikeusc-resources")
                                        .WithCannedACL(S3CannedACL.PublicRead)
                                        .WithKey("videos/" + filename.PostedFile.FileName).InputStream = filename.PostedFile.InputStream;
                                }                                 
                                
                                string fileType = filename.PostedFile.ContentType;
                                string vidId = UploadVideo("https://s3-ap-southeast-1.amazonaws.com/ilikeusc-resources/videos/" + filename.PostedFile.FileName, fileType, textEntry.Value, entrantName.Value);
                                add.Parameters.AddWithValue("@fileValue", "http://www.youtube.com/embed/" + vidId);
                                add.Parameters.AddWithValue("@typeValue", "video");
                            }
                        }
                        else
                        {
                            add.Parameters.AddWithValue("@typeValue", "text");
                        }

                        add.ExecuteNonQuery();

                        status.InnerHtml = "Thank you for entering";
                        GetEntries();
                        GetFinalists();
                    }
                }
                catch (Exception ex)
                {
                    status.InnerHtml = "Something went wrong..." + ex.Message;
                }

            }
        }
    }
}